package utils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * Created by sdliang on 2018/4/13.
 */
public class CollectionHelper {

  /**
   * 获取集合元素中的某个属性列表
   *
   * @param list
   * @param keyExtractor 属性方法
   * @param <T>
   * @param <R>
   * @return
   */
  public static <T, R> List<R> getPropertyList(Collection<T> list,
                                               Function<? super T, ? extends R> keyExtractor) {
    List<R> result = new CopyOnWriteArrayList<>();
    list.parallelStream().map(keyExtractor::apply).forEach(result::add);
    return result;
  }

  /**
   * 数据去重操作
   *
   * @param list         源数组
   * @param keyExtractor 判断重复的条件
   * @param <T>
   * @return
   */
  public static <T> List<T> distinct(List<T> list, Function<? super T, ?> keyExtractor) {
    List<T> newList = new CopyOnWriteArrayList();
    list.parallelStream().filter(distinctByKey(keyExtractor)).forEach(newList::add);
    return newList;
  }

  /**
   * 排序操作
   *
   * @param list         源集合
   * @param keyExtractor 排序条件
   * @param <T>
   */
  public static <T> void sort(List<T> list,
                              Function<? super T, ? extends Comparable> keyExtractor) {
    list.sort((o1, o2) -> keyExtractor.apply(o1).compareTo(keyExtractor.apply(o2)));
  }

  private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
    Set<Object> seen = ConcurrentHashMap.newKeySet();
    return t -> seen.add(keyExtractor.apply(t));
  }


  public static void main(String[] args) {
    List<User> list = new ArrayList<>();
    for (int i = 0; i < 10000; i++) {
      list.add(new User(i, "user:" + i));
      list.add(new User(i + 1, "user:" + (i + 1)));
    }
    List<User> distinctList = distinct(list, User::getI);
    List<String> userIds = getPropertyList(distinctList, User::getName);
    userIds.forEach(System.out::println);
  }

  private static class User {

    private final int i;
    private String name;

    public User(int i, String name) {
      this.i = i;
      this.name = name;
    }

    public String getName() {
      return name;
    }

    public void setName(String name) {
      this.name = name;
    }

    public int getI() {
      return i;
    }

    @Override
    public String toString() {
      return "user:" + i;
    }
  }

}
